using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

[System.Serializable]
public class DamageResultEvent : UnityEvent<DamageResult> { }

[System.Serializable]
public class RefreshStatusEvent : UnityEvent<Status> { }

public class Status
{
    private int maxHP;
    private int currentHP;
    private bool isInvincible;
    public RefreshStatusEvent refreshStatusEvent;
    public Status(int maxHP, int currentHP, bool isInvincible, RefreshStatusEvent rEvent)
    {
        this.maxHP = maxHP;
        this.currentHP = currentHP;
        this.isInvincible = isInvincible;
        this.refreshStatusEvent = rEvent;
        refreshStatusEvent.Invoke(this);
    }
    public int GetMaxHP { get { return maxHP; } }
    public int GetCurrentHP { get { return currentHP; } }
    public bool IsInvincible { get { return isInvincible; } }
    public bool AddHP(int amount)
    {
        if (currentHP + amount > 0)
        {
            if (isInvincible && amount < 0)
            {
                return false;
            }
            else
            {
                currentHP += amount;
                refreshStatusEvent.Invoke(this);
                return true;
            }
        }
        else
        {
            return false;
        }
    }
}

public class Damageable : MonoBehaviour
{
    [SerializeField] private GameObject explosionFX;
    [SerializeField] private int maxHP = 100;
    public int camp = 0;
    public DamageResultEvent damageResultEvent;
    public RefreshStatusEvent refreshStatusEvent;
    private Status status;
    // Start is called before the first frame update
    void Start()
    {
        status = new Status(maxHP, maxHP, false, refreshStatusEvent);
        if (damageResultEvent == null)
        {
            damageResultEvent = new DamageResultEvent();
        }
    }

    // Update is called once per frame
    void Update()
    {

    }

    public bool GetDamage(Damage damage)
    {
        OnDamage(damage);
        return true;
    }
    private void OnDamage(Damage damage)
    {
        int hp_before = status.GetCurrentHP;
        int dmg = damage.GetAmount;
        int hp_after = 0;
        bool isDead = false;
        if (hp_before > dmg)
        {
            isDead = false;
        }
        else
        {
            dmg = hp_before;
            isDead = true;
        }
        hp_after = hp_before - dmg;
        damageResultEvent.Invoke(new DamageResult(hp_before, hp_after, isDead, damage));

        status.AddHP(-dmg);
        if (isDead)
        {
            Death();
        }
    }

    private void Death()
    {
        GameObject fx = Instantiate(explosionFX);
        fx.transform.position = transform.position;
        Destroy(this.gameObject);
    }
}
